Public Class Receipt
    Public SalonName As String = String.Empty
    Public CustomerName As String = String.Empty
    Public Time As DateTime = Now
    Public Services As ArrayList = New ArrayList
    Public Cash As Decimal = 0
    Public Cheque As Decimal = 0
    Public Card As Decimal = 0
    Public Total As Decimal = 0
End Class


Public Class TillManager
    Public Enum Port
        LPT1
        LPT2
    End Enum

    Public Enum TillOpenCode
        [Default]
        Deffered
        Immediate
    End Enum

    Private mPortMan As ParallelComms

    Private mPortNum As Port = Port.LPT1
    Public Property PortNum() As Port
        Get
            Return mPortNum
        End Get
        Set(ByVal Value As Port)
            mPortNum = Value
        End Set
    End Property


    Private mOpenCode As TillOpenCode = TillOpenCode.Deffered
    Public Property OpenCode() As TillOpenCode
        Get
            Return mOpenCode
        End Get
        Set(ByVal Value As TillOpenCode)
            Me.mOpenCode = Value
        End Set
    End Property

    Private mOpenSequence As String = Chr(91) + Chr(91)
    Public Property OpenSequence() As String
        Get
            Return Me.mOpenCode
        End Get
        Set(ByVal Value As String)
            Me.mOpenCode = Value
        End Set
    End Property

    Public Sub TillOpen()

        Dim openSequence As String
        'Adding Code sequence that redirect input to cash drawer
        Select Case OpenCode
            Case TillOpenCode.Default
                openSequence &= ControlCodes.DefaultPeriferialPulse
            Case TillOpenCode.Deffered
                openSequence &= ControlCodes.DefferedPeriferialPulse
            Case TillOpenCode.Immediate
                openSequence &= ControlCodes.ImmidiatePeriferialPulse
        End Select

        'Adding char sequence to open Till
        openSequence &= Me.mOpenSequence

        'Writing open sequence to Port
        If (Not Opened) Then
            Throw New TillException("You should call Open() operarion first.")
        End If
        mPortMan.WriteParallelPort(openSequence)
    End Sub

    Public Sub PrintReceipt(ByVal r As Receipt)
        PrintReceipt(r.SalonName, r.CustomerName, r.Time, r.Services, r.Cash, r.Cheque, r.Card, r.Total)
    End Sub


    Private Function FormatString(ByVal s As String) As String
        If s.Length > 9 Then
            Return s.Substring(0, 8) & " -"
        Else
            Return s & " " & (New String("-", 9 - s.Length))
        End If
    End Function

    Private Function FormatMoney(ByVal m As Decimal) As String
        Return String.Format("{0,6:f2}", m)
    End Function

    Public Sub PrintReceipt(ByVal salonName As String, ByVal customerName As String, _
        ByVal time As DateTime, ByVal services As ArrayList, _
        ByVal cash As Decimal, ByVal cheque As Decimal, ByVal card As Decimal, ByVal total As Decimal)

        Dim receipt As String
        receipt &= ControlCodes.InitializePrinter
        receipt &= salonName & ControlCodes.StarLineFeed
        receipt &= customerName & ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed
        receipt &= String.Format("Date: {0:d}", time) & ControlCodes.StarLineFeed
        receipt &= String.Format("Time: {0:t}", time) & ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed

        For Each ri As ReceiptItem In services
            receipt &= String.Format("{0} {1}{2}", FormatString(ri.ServiceName), FormatMoney(ri.Amount), ControlCodes.StarLineFeed)
        Next

        receipt &= ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed
        'receipt &= String.Format("{0} {1}{2}", FormatString("Cash"), FormatMoney(cash), ControlCodes.StarLineFeed)
        'receipt &= String.Format("{0} {1}{2}", FormatString("Card"), FormatMoney(card), ControlCodes.StarLineFeed)
        'receipt &= String.Format("{0} {1}{2}", FormatString("Cheque"), FormatMoney(cheque), ControlCodes.StarLineFeed)
        'receipt &= ControlCodes.StarLineFeed
        receipt &= String.Format("{0} {1}{2}", FormatString("Total"), FormatMoney(total), ControlCodes.StarLineFeed)
        receipt &= ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed
        receipt &= ControlCodes.StarLineFeed
        receipt &= ControlCodes.Cut

        'Dim writer As IO.StreamWriter = New IO.StreamWriter(IO.File.Create("receipt.txt"))
        'writer.Write(receipt)
        'writer.Close()

        mPortMan.WriteParallelPort(receipt)
    End Sub

    Public Sub Open()

        Select Case PortNum
            Case Port.LPT1
                mPortMan = New ParallelComms("LPT1")
            Case Port.LPT2
                mPortMan = New ParallelComms("LPT2")
        End Select

        If Not Opened Then
            mPortMan = Nothing
            Throw New TillException(Res.PortInitializationFailed)
        End If
    End Sub

    Public Sub Close()
        mPortMan.CloseParallelPort()
        mPortMan = Nothing
    End Sub

    Public ReadOnly Property Opened() As Boolean
        Get
            If mPortMan Is Nothing Then Return False
            Return mPortMan.isOpen
        End Get
    End Property

End Class
